﻿using System;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using BSF.Log;

namespace HuntingFishGame.CustomerApiTest
{
    //贴在方法上的标签
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class MyInterceptorMethodAttribute : Attribute { }

    //贴在类上的标签
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public sealed class MyInterceptorAttribute : ContextAttribute, IContributeObjectSink
    {
        /// <summary>
        /// 构造方法
        /// </summary>
        public MyInterceptorAttribute()
            : base("MyInterceptor")
        { }

        //实现IContributeObjectSink接口当中的消息接收器接口
        public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next)
        {
            return new MyAopHandler(next);
        }
    }

    //AOP方法处理类，实现了IMessageSink接口，以便返回给IContributeObjectSink接口的GetObjectSink方法
    public sealed class MyAopHandler : IMessageSink
    {
        //下一个接收器
        private IMessageSink nextSink;
        public IMessageSink NextSink
        {
            get { return nextSink; }
        }
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="nextSink"></param>
        public MyAopHandler(IMessageSink nextSink)
        {
            this.nextSink = nextSink;
        }

        //同步处理方法
        public IMessage SyncProcessMessage(IMessage msg)
        {
            IMessage retMsg = null;

            //方法调用消息接口
            IMethodCallMessage call = msg as IMethodCallMessage;

            //如果被调用的方法没打MyInterceptorMethodAttribute标签
            if (call == null || (Attribute.GetCustomAttribute(call.MethodBase, typeof(MyInterceptorMethodAttribute))) == null)
            {
                retMsg = nextSink.SyncProcessMessage(msg);
            }
            //如果打了MyInterceptorMethodAttribute标签
            else
            {
                CommLog.Write("执行之前");
                //执行前后具体操作部分代码，相当于一个“代理类”，它实质上是改变了方法执行的上下文。可以用委托等面向对象程序结构把具体实现暴露给外部进行二次开发。
                retMsg = nextSink.SyncProcessMessage(msg);
                CommLog.Write("执行之后");
            }

            return retMsg;
        }

        //异步处理方法（不需要）
        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            return null;
        }
    }
}
